package jupitermouse.site.juc.demo.collection;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * DelayQueue：带有延迟时间的Queue
 * 其中的元素只有当其指定的延迟时间到了，才能够从队列中获取到该元素。
 * DelayQueue中的元素必须实现Delayed接口，DelayQueue是一个没有大小限制的队列，
 * 应用场景很多，比如对缓存超时的数据进行移除、 任务超时处理、空闲连接的关闭等等
 *
 * </p>
 *
 * @author jupiter
 */
public class DelayQueueApp {
    public static void main(String[] args) {
        WangBa wangb = new WangBa();
        System.err.println("网吧正常营业: ");
        Thread yingye = new Thread(wangb);
        yingye.start();

        wangb.startMachine("001", "张三", 2);
        wangb.startMachine("002", "李四", 5);
        wangb.startMachine("003", "王五", 10);
    }
}

class WangBa implements Runnable {
    // 队列
    private DelayQueue<WangMin> queue = new DelayQueue<>();

    // 营业状态
    private boolean start = true;

    public void startMachine(String id, String name, int money) {
        WangMin wm = new WangMin(id, name, System.currentTimeMillis() + money * 1000);
        System.err.println("网名: " + name + ", 身份证: " + id + ", 缴费: " + money + "元, 开始上网!");
        queue.add(wm);
    }

    public void overMachine(WangMin wm) {
        System.err.println("网名: " + wm.getName() + ", 身份证: " + wm.getId() + ", 已经到了下机时间!");
    }

    @Override
    public void run() {
        while (start) {
            try {
                WangMin wm = queue.take();
                overMachine(wm);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

@Data
@NoArgsConstructor
@AllArgsConstructor
class WangMin implements Delayed {
    private String id;
    private String name;
    private long endTime;

    @Override
    public long getDelay(TimeUnit unit) {
        return endTime - System.currentTimeMillis();
    }

    @Override
    public int compareTo(Delayed o) {
        WangMin w = (WangMin) o;
        return this.getDelay(TimeUnit.SECONDS) - w.getDelay(TimeUnit.SECONDS) > 0 ? 1 : -1;
    }
}
